package mock;

import bean.OrderDetail;
import bean.OrderInfo;
import com.github.javafaker.Faker;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class OrderInfoDataGenerator {
    private static final String DB_URL = "jdbc:mysql://192.168.10.102:3306/driver?useSSL=false&requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 100;

    // 缓存 driver_id, passenger_id, city_id 避免重复查询
    private static List<String> driverIds = null;
    private static List<String> passengerIds = null;
    private static List<String> cityIds = null;
    private static List<String> CarIds = null;

    public static void main(String[] args) {
        int count = 10; // 默认生成10条数据
        LocalDateTime startTime = LocalDateTime.now().minusDays(1); // 默认从1年前开始

        LocalDateTime endTime = LocalDateTime.now(); // 到现在为止

        // 解析命令行参数
        if (args.length >= 1) {
            count = Integer.parseInt(args[0]);
        }
        if (args.length >= 4) {
            startTime = LocalDateTime.of(
                    Integer.parseInt(args[1]), // 年
                    Integer.parseInt(args[2]), // 月
                    Integer.parseInt(args[3]), // 日
                    0, 0); // 时分设为0
        }
        if (args.length >= 7) {
            endTime = LocalDateTime.of(
                    Integer.parseInt(args[4]), // 年
                    Integer.parseInt(args[5]), // 月
                    Integer.parseInt(args[6]), // 日
                    23, 59); // 时分设为23:59
        }

        generateData(count, startTime, endTime);
    }

    public static void generateData(int count, LocalDateTime startTime, LocalDateTime endTime) {
//        Faker faker = new Faker(Locale.CHINA);
//        List<OrderInfo> orders = new ArrayList<>();
//
//        // 初始化外键缓存
//        if (driverIds == null || driverIds.isEmpty()) {
//            driverIds = getAllDriverIds();
//        }
//        if (passengerIds == null || passengerIds.isEmpty()) {
//            passengerIds = getAllPassengerIds();
//        }
//        if (cityIds == null || cityIds.isEmpty()) {
//            cityIds = getAllCityIds();
//        }
//        if (CarIds == null || CarIds.isEmpty()) {
//            CarIds = getAllCarIds();
//        }
//
//        for (long i = 1; i <= count; i++) {
//            LocalDateTime createTime = randomLocalDateTime(faker, startTime, endTime);
//            // 更新时间在创建时间之后，但不超过当前时间
//            LocalDateTime updateTime = randomLocalDateTime(faker,
//                    createTime,
//                    endTime.isAfter(LocalDateTime.now()) ? LocalDateTime.now() : endTime);
//            OrderInfo order = OrderInfo.builder()
//                    .order_id(String.valueOf(i))
//                    .city_id(getRandomCityId(faker))
//                    .passenger_id(getRandomPassengerId(faker))
//                    .driver_id(getRandomDriverId(faker))
//                    .car_id(getRandomCarId(faker))
//                    .start_time(createTime)
//                    .end_time(updateTime)
//                    .total_price(generateRandomPrice(faker))
//                    .status(generateRandomStatus(faker))
//                    .build();
//
//            orders.add(order);
//        }
//
//        insertIntoDatabase(orders);
        Faker faker = new Faker(Locale.CHINA);
        List<OrderInfo> orders = new ArrayList<>();

        int currentMaxId = getCurrentMaxOrderId();

        // 初始化外键缓存
        if (driverIds == null || driverIds.isEmpty()) driverIds = getAllDriverIds();
        if (passengerIds == null || passengerIds.isEmpty()) passengerIds = getAllPassengerIds();
        if (cityIds == null || cityIds.isEmpty()) cityIds = getAllCityIds();
        if (CarIds == null || CarIds.isEmpty()) CarIds = getAllCarIds();

        for (long i = 1; i <= count; i++) {
            LocalDateTime createTime = randomLocalDateTime(faker, startTime, endTime);
            LocalDateTime updateTime = randomLocalDateTime(faker,
                    createTime,
                    endTime.isAfter(LocalDateTime.now()) ? LocalDateTime.now() : endTime);

            String orderId = String.valueOf(currentMaxId + i);

            OrderInfo order = OrderInfo.builder()
                    .order_id(orderId)
                    .city_id(getRandomCityId(faker))
                    .passenger_id(getRandomPassengerId(faker))
                    .driver_id(getRandomDriverId(faker))
                    .car_id(getRandomCarId(faker))
                    .start_time(createTime)
                    .end_time(updateTime)
                    .total_price(generateRandomPrice(faker))
                    .status(generateRandomStatus(faker))
                    .build();

            orders.add(order);
        }

        insertIntoDatabase(orders);

    }

    private static void insertIntoDatabase(List<OrderInfo> orders) {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);
            String sql = "INSERT INTO order_info (" +
                    "order_id, city_id, passenger_id, driver_id, car_id,start_time, end_time, total_price, status" +
                    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?,?)";

            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                for (int i = 0; i < orders.size(); i++) {
                    OrderInfo o = orders.get(i);
                    pstmt.setString(1, o.getOrder_id());
                    pstmt.setString(2, o.getCity_id());
                    pstmt.setString(3, o.getPassenger_id());
                    pstmt.setString(4, o.getDriver_id());
                    pstmt.setString(5, o.getCar_id());
                    pstmt.setTimestamp(6, Timestamp.valueOf(o.getStart_time()));
                    pstmt.setTimestamp(7, Timestamp.valueOf(o.getEnd_time()));
                    pstmt.setDouble(8, o.getTotal_price());
                    pstmt.setInt(9, o.getStatus());
                    pstmt.addBatch();

                    if ((i + 1) % BATCH_SIZE == 0 || i == orders.size() - 1) {
                        pstmt.executeBatch();
                    }
                }
                conn.commit();
                System.out.println("成功插入" + orders.size() + "条订单信息");
            } catch (SQLException e) {
                conn.rollback();
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static String getRandomDriverId(Faker faker) {
        return driverIds.get(faker.random().nextInt(driverIds.size()));
    }

    private static String getRandomPassengerId(Faker faker) {
        return passengerIds.get(faker.random().nextInt(passengerIds.size()));
    }

    private static String getRandomCityId(Faker faker) {
        return cityIds.get(faker.random().nextInt(cityIds.size()));
    }

    public static String getRandomCarId(Faker faker) {
        return CarIds.get(faker.random().nextInt(CarIds.size()));
    }

    private static Timestamp generateRandomTimestamp(Faker faker) {
        return new Timestamp(faker.date().past(365, TimeUnit.DAYS).getTime());
    }

    private static Timestamp generateRandomEndTimestamp(Faker faker, long startTimeMillis) {
        long durationMillis = faker.number().numberBetween(5 * 60 * 1000L, 60 * 60 * 1000L); // 5分钟~1小时
        return new Timestamp(startTimeMillis + durationMillis);
    }

    private static double generateRandomPrice(Faker faker) {
        return Math.round(faker.number().randomDouble(2, 10, 300) * 100.0) / 100.0;
    }

    private static int generateRandomStatus(Faker faker) {
        return faker.random().nextInt(0, 3); // 状态：0（未完成）~3（超时）
    }

    /**
     * 查询所有 driver_id
     */
    public static List<String> getAllDriverIds() {
        List<String> ids = new ArrayList<>();
        String query = "SELECT driver_id FROM driver";

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                ids.add(rs.getString("driver_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return ids;
    }

    /**
     * 查询所有 passenger_id
     */
    public static List<String> getAllPassengerIds() {
        List<String> ids = new ArrayList<>();
        String query = "SELECT passenger_id FROM passenger";

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                ids.add(rs.getString("passenger_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return ids;
    }

    /**
     * 查询所有 city_id
     */
    public static List<String> getAllCityIds() {
        List<String> ids = new ArrayList<>();
        String query = "SELECT city_id FROM city";

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                ids.add(rs.getString("city_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return ids;
    }
    //查询所有carid
    public static List<String> getAllCarIds() {
        List<String> ids = new ArrayList<>();
        String query = "SELECT car_id FROM car";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                ids.add(rs.getString("car_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ids;
    }

    private static LocalDateTime randomLocalDateTime(Faker faker, LocalDateTime start, LocalDateTime end) {

        ZonedDateTime startZoned = start.atZone(ZoneId.systemDefault());
        ZonedDateTime endZoned = end.atZone(ZoneId.systemDefault());

        long startEpoch = startZoned.toInstant().toEpochMilli();
        long endEpoch = endZoned.toInstant().toEpochMilli();

        long randomEpoch = faker.date().between(
                new Date(startEpoch),
                new Date(endEpoch)
        ).getTime();

        return LocalDateTime.ofInstant(
                java.time.Instant.ofEpochMilli(randomEpoch),
                ZoneId.systemDefault()
        );
    }
    public static int getCurrentMaxOrderId() {
        String query = "SELECT MAX(CAST(order_id AS UNSIGNED)) FROM order_info";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

}
